import { flatten, isArray, lngLatToWorld, getNormals, polylineNormalToNormal } from '../components/GisMap/util'
import { Vector3 } from 'three/src/math/Vector3'
import { Vector2 } from 'three/src/math/Vector2'
import { BufferGeometry } from 'three/src/core/BufferGeometry'
import { BufferAttribute } from 'three/src/core/BufferAttribute'

function transformCoordinate(center, aimPos) {
  return new Vector2(aimPos[0] - center[0], center[1] - aimPos[1])
}

export function getGeographicPolylineFormat(gisCenterPos, path) {
  const _path = []
  for (let i = 0; i < path.length; i++) {
    const unitPath = path[i]
    let formatPath = []
    formatPath = unitPath.map((vec) => {
      const pos = lngLatToWorld([vec.x, vec.y])
      const format = transformCoordinate(gisCenterPos, pos)
      return new Vector3(format.x, format.y, vec.z)
    })
    _path.push(formatPath)
  }
  return _path
}

export function formatPolylinePath(geojsonArr) {
  const formatPath = []
  for (let i = 0; i < geojsonArr.length; i++) {
    const type = geojsonArr[i].geometry && geojsonArr[i].geometry.type
    if (type === 'MultiLineString') {
      const coordinates = geojsonArr[i].geometry.coordinates
      let j = 0
      while (j < coordinates.length) {
        const coordinate = coordinates[j]
        const path = []
        for (let k = 0, len = coordinate.length; k < len; k++) {
          path.push(new Vector3(coordinate[k][0], coordinate[k][1], 0))
        }
        formatPath.push(path)
        j++
      }
    } else if (type === 'LineString') {
      const coordinates = geojsonArr[i].geometry.coordinates
      if (isArray(coordinates) && coordinates.length === 1) {
        const coordinate = coordinates[0]
        const path = []
        for (let j = 0, len = coordinate.length; j < len; j++) {
          path.push(new Vector3(coordinate[j][0], coordinate[j][1], 0))
        }
        formatPath.push(path)
      } else {
        const path = []
        for (let j = 0, len = coordinates.length; j < len; j++) {
          path.push(new Vector3(coordinates[j][0], coordinates[j][1], 0))
        }
        formatPath.push(path)
      }
    } else if (!type) {
      const coordinates = geojsonArr[i]
      formatPath.push(coordinates)
    }
  }
  return formatPath
}

export function getPolylineGeometry(gisCenterPos, geojsonArr) {
  const formatPath = formatPolylinePath(geojsonArr)
  const paths = getGeographicPolylineFormat(gisCenterPos, formatPath)
  let facenormals = []
  let positions = []
  let uvs = []
  let baseUVYLength = 0
  for (let o = 0; o < paths.length; o++) {
    const unitPath = paths[o]
    const xys1 = []
    for (let i = 0; i < unitPath.length; i++) {
      const point = unitPath[i]
      xys1.push([point.x, point.y])
    }

    const normals = getNormals(xys1, false)
    const xys = flatten(xys1)
    const position = []
    const uv = []
    const faceNormal = []

    // 获得每一段的长度
    const xySegLength = []
    for (let i = 0, j = 0; i < xys.length - 2; i += 2, j++) {
      if (i === 0) {
        xySegLength[0] = Math.sqrt((xys[2] - xys[0]) * (xys[2] - xys[0]) + (xys[3] - xys[1]) * (xys[3] - xys[1]))
      } else {
        xySegLength[j] = xySegLength[j - 1] + Math.sqrt((xys[i + 2] - xys[i]) * (xys[i + 2] - xys[i]) + (xys[i + 3] - xys[i + 1]) * (xys[i + 3] - xys[i + 1]))
      }
    }

    baseUVYLength = xySegLength[xySegLength.length - 1]
    // 处理第一个点
    const trianglesLength = position.length
    const uvLength = uv.length
    // 结合第n个点和第n+1个点
    const segLength = xySegLength[0]
    const positiveNormal = polylineNormalToNormal(normals[0][0], normals[0][1])
    const reverseNormal = polylineNormalToNormal(normals[0][0], -normals[0][1])
    let positiveNormal1 = 0
    let reverseNormal1 = 0

    // let segLength1 = xySegLength[1] - xySegLength[0]
    positiveNormal1 = polylineNormalToNormal(normals[1][0], normals[1][1])
    reverseNormal1 = polylineNormalToNormal(normals[1][0], -normals[1][1])
    // 第一个点
    position[trianglesLength + 0] = xys[0]
    position[trianglesLength + 1] = xys[1]
    position[trianglesLength + 2] = 0
    // 平面法向量
    faceNormal[trianglesLength + 0] = positiveNormal[0]
    faceNormal[trianglesLength + 1] = positiveNormal[1]
    faceNormal[trianglesLength + 2] = 0
    // uv
    uv[uvLength + 0] = 0
    uv[uvLength + 1] = 1
    // 第二个点
    position[trianglesLength + 3] = xys[0]
    position[trianglesLength + 4] = xys[1]
    position[trianglesLength + 5] = 0
    // 平面法向量
    faceNormal[trianglesLength + 3] = reverseNormal[0]
    faceNormal[trianglesLength + 4] = reverseNormal[1]
    faceNormal[trianglesLength + 5] = 0
    // uv
    uv[uvLength + 2] = 0
    uv[uvLength + 3] = 0
    // 第三个点
    position[trianglesLength + 6] = xys[2]
    position[trianglesLength + 7] = xys[3]
    position[trianglesLength + 8] = 0
    // 平面法向量
    faceNormal[trianglesLength + 6] = reverseNormal1[0]
    faceNormal[trianglesLength + 7] = reverseNormal1[1]
    faceNormal[trianglesLength + 8] = 0
    // uv
    uv[uvLength + 4] = segLength / baseUVYLength
    uv[uvLength + 5] = 0
    // 第四个点
    position[trianglesLength + 9] = xys[0]
    position[trianglesLength + 10] = xys[1]
    position[trianglesLength + 11] = 0
    // 平面法向量
    faceNormal[trianglesLength + 9] = positiveNormal[0]
    faceNormal[trianglesLength + 10] = positiveNormal[1]
    faceNormal[trianglesLength + 11] = 0
    // uv
    uv[uvLength + 6] = 0
    uv[uvLength + 7] = 1
    // 第五个点
    position[trianglesLength + 12] = xys[2]
    position[trianglesLength + 13] = xys[3]
    position[trianglesLength + 14] = 0
    // 平面法向量
    faceNormal[trianglesLength + 12] = reverseNormal1[0]
    faceNormal[trianglesLength + 13] = reverseNormal1[1]
    faceNormal[trianglesLength + 14] = 0
    // uv
    uv[uvLength + 8] = segLength / baseUVYLength
    uv[uvLength + 9] = 0
    // 第六个点
    position[trianglesLength + 15] = xys[2]
    position[trianglesLength + 16] = xys[3]
    position[trianglesLength + 17] = 0
    // 平面法向量
    faceNormal[trianglesLength + 15] = positiveNormal1[0]
    faceNormal[trianglesLength + 16] = positiveNormal1[1]
    faceNormal[trianglesLength + 17] = 0
    // uv
    uv[uvLength + 10] = segLength / baseUVYLength
    uv[uvLength + 11] = 1

    // 处理其他点
    for (let i = 2, j = 1; i < xys.length - 2; i = i + 2, j++) {
      const trianglesLength = position.length
      const uvLength = uv.length
      // 结合第n个点和第n+1个点
      const segLength = (i === 0 ? xySegLength[0] : xySegLength[j])
      let positiveNormal = 0
      let reverseNormal = 0
      // if (i !== xys.length - 4) {
      positiveNormal = polylineNormalToNormal(normals[j + 1][0], normals[j + 1][1])
      reverseNormal = polylineNormalToNormal(normals[j + 1][0], -normals[j + 1][1])
      // console.log(positiveNormal, lastPositiveNormal, reverseNormal, lastReverseNormal, positiveNormalLength, reverseNormalLength)
      // } else {
      //   positiveNormal = lineNormalHole(xys[i - 2], xys[i - 1], xys[i], xys[i + 1], segLength)
      //   reverseNormal = lineNormalFace(xys[i - 2], xys[i - 1], xys[i], xys[i + 1], segLength)
      // }
      // 第一个点
      position[trianglesLength + 0] = xys[i]
      position[trianglesLength + 1] = xys[i + 1]
      position[trianglesLength + 2] = 0
      // 平面法向量
      faceNormal[trianglesLength + 0] = faceNormal[trianglesLength - 3]
      faceNormal[trianglesLength + 1] = faceNormal[trianglesLength - 2]
      faceNormal[trianglesLength + 2] = 0
      // uv
      uv[uvLength + 0] = uv[uvLength - 2]
      uv[uvLength + 1] = uv[uvLength - 1]
      // 第二个点
      position[trianglesLength + 3] = xys[i]
      position[trianglesLength + 4] = xys[i + 1]
      position[trianglesLength + 5] = 0
      // 平面法向量
      faceNormal[trianglesLength + 3] = faceNormal[trianglesLength - 6]
      faceNormal[trianglesLength + 4] = faceNormal[trianglesLength - 5]
      faceNormal[trianglesLength + 5] = 0
      // uv
      uv[uvLength + 2] = uv[uvLength - 4]
      uv[uvLength + 3] = uv[uvLength - 3]
      // 第三个点
      position[trianglesLength + 6] = xys[i + 2]
      position[trianglesLength + 7] = xys[i + 3]
      position[trianglesLength + 8] = 0
      // 平面法向量
      faceNormal[trianglesLength + 6] = reverseNormal[0]
      faceNormal[trianglesLength + 7] = reverseNormal[1]
      faceNormal[trianglesLength + 8] = 0
      // uv
      uv[uvLength + 4] = segLength / baseUVYLength
      uv[uvLength + 5] = 0
      // 第四个点
      position[trianglesLength + 9] = xys[i]
      position[trianglesLength + 10] = xys[i + 1]
      position[trianglesLength + 11] = 0
      // 平面法向量
      faceNormal[trianglesLength + 9] = faceNormal[trianglesLength - 3]
      faceNormal[trianglesLength + 10] = faceNormal[trianglesLength - 2]
      faceNormal[trianglesLength + 11] = 0
      // uv
      uv[uvLength + 6] = uv[uvLength - 2]
      uv[uvLength + 7] = uv[uvLength - 1]
      // 第五个点
      position[trianglesLength + 12] = xys[i + 2]
      position[trianglesLength + 13] = xys[i + 3]
      position[trianglesLength + 14] = 0
      // 平面法向量
      faceNormal[trianglesLength + 12] = reverseNormal[0]
      faceNormal[trianglesLength + 13] = reverseNormal[1]
      faceNormal[trianglesLength + 14] = 0
      // uv
      uv[uvLength + 8] = segLength / baseUVYLength
      uv[uvLength + 9] = 0
      // 第六个点
      position[trianglesLength + 15] = xys[i + 2]
      position[trianglesLength + 16] = xys[i + 3]
      position[trianglesLength + 17] = 0
      // 平面法向量
      faceNormal[trianglesLength + 15] = positiveNormal[0]
      faceNormal[trianglesLength + 16] = positiveNormal[1]
      faceNormal[trianglesLength + 17] = 0
      // uv
      uv[uvLength + 10] = segLength / baseUVYLength
      uv[uvLength + 11] = 1
      // lastPositiveNormal = positiveNormal
      // lastReverseNormal = reverseNormalattribute
    }
    facenormals = facenormals.concat(faceNormal)
    positions = positions.concat(position)
    uvs = uvs.concat(uv)
  }
  const facenormalsBuffer = new Float32Array(facenormals)
  const positionsBuffer = new Float32Array(positions)
  const uvsBuffer = new Float32Array(uvs)

  const geometry = new BufferGeometry()
  geometry.setAttribute('facenormal', new BufferAttribute(facenormalsBuffer, 3))
  geometry.setAttribute('position', new BufferAttribute(positionsBuffer, 3))
  geometry.setAttribute('uv', new BufferAttribute(uvsBuffer, 2))

  return geometry
}
